Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 14.10.2017, 17:32
Новичок на форуме
Отправить личное сообщение для MikhailM1993 Посмотреть профиль Найти все сообщения от MikhailM1993
 
Регистрация: 14.10.2017
Сообщений: 5

Ajax корзина на сайте. Помощь.
Добрый день! Подскажите как реализовать корзину на сайте методом ajax. Я не силён в js поэтому если можно объясните как новичку. Я не понимаю как средствами ajax добавить товар в массив $_SESSION['cart']? Да и вообще как должна правильно работать ajax корзина? Я хочу что бы при нажатии на ссылку "добавить в корзину" всплывал alert с текстом "Товар успешно добавлен в корзину" и соответственно сам товар добавлялся в массив $_SESSION['cart'].
Заранее большое спасибо!


На данный момент у меня так:

HTML:
Так выводятся товары:
<div class="goods">
<a href="?view=product&amp;goods_id=<?=$product['goods_id']?>"><img width="200" height="200" src="<?=PRODUCTIMG?><?=$product['img']?>" alt="Картинка товара" /></a>
<a class="good_name" href="?view=product&amp;goods_id=<?=$product['goods_id']?>"><?=$product['name']?></a>
<p class="price">Цена: <span><?=$product['price']?> р.</span></p>
<a href="?view=addtocart&amp;goods_id=<?=$product['goods_id']?>"><img class="addtocart" src="<?=TEMPLATE?>images/addcart.png" alt="Добавить в корзину" /></a>
</div><!-- .goods -->


Такой блок корзины:
<div class="basket">
<?php if($_SESSION['total_quantity']): ?>
<a href="?view=cart"><img src="<?=TEMPLATE?>images/cart.png" alt="Корзина" /></a>
<h4>Товаров в <a href="?view=cart">Вашей корзине:</a><br /> <span><?=$_SESSION['total_quantity']?></span> на сумму <span><?=$_SESSION['total_sum']?></span> руб.</h4>
<?php else: ?>
<a href="?view=cart"><img src="<?=TEMPLATE?>images/cart.png" alt="Корзина" /></a>
<h4>Товаров в <a href="?view=cart">Вашей корзине:</a>&nbsp;<span>0</span></h4>
<?php endif; ?>
</div>

При клике на ссылку "добавить в корзину" срабатывают функции:
PHP

addtocart:
function addtocart($goods_id, $qty = 1){
if(isset($_SESSION['cart'][$goods_id])){
// если в массиве cart уже есть добавляемый товар
$_SESSION['cart'][$goods_id]['qty'] += $qty;
return $_SESSION['cart'];
}else{
// если товар кладется в корзину впервые
$_SESSION['cart'][$goods_id]['qty'] = $qty;
return $_SESSION['cart'];
}
}

total_sum:
function total_sum($goods){

$total_sum = 0;

$query = "SELECT goods_id, name, price, img
FROM goods
WHERE goods_id IN (" .implode(',',array_keys($goods)). ")";


$res = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_assoc($res)){
$_SESSION['cart'][$row['goods_id']]['name'] = $row['name'];
$_SESSION['cart'][$row['goods_id']]['price'] = $row['price'];
$_SESSION['cart'][$row['goods_id']]['img'] = $row['img'];
$total_sum += $_SESSION['cart'][$row['goods_id']]['qty'] * $row['price'];
}
return $total_sum;
}

total_quantity
function total_quantity(){
$_SESSION['total_quantity'] = 0;
foreach($_SESSION['cart'] as $key => $value){
if(isset($value['price'])){
// если получена цена товара из БД - суммируем кол-во
$_SESSION['total_quantity'] += $value['qty'];
}else{
// иначе - удаляем такой ID из сессиии (корзины)
unset($_SESSION['cart'][$key]);
}
}
}
Ответить с цитированием
  #2 (permalink)  
Старый 14.10.2017, 17:54
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

MikhailM1993,
корзина должна хранить не только количество товара, но и его цену, иначе при каждом обращении к корзине вы третируете базу запросами, так как добавление/изменение/удаление в корзине требует перерасчета.

Ajax всего лишь метод обмена с сервером, а все работать будет точно также.
Ответить с цитированием
  #3 (permalink)  
Старый 14.10.2017, 20:50
Новичок на форуме
Отправить личное сообщение для MikhailM1993 Посмотреть профиль Найти все сообщения от MikhailM1993
 
Регистрация: 14.10.2017
Сообщений: 5

Сообщение от laimas Посмотреть сообщение
MikhailM1993,
корзина должна хранить не только количество товара, но и его цену, иначе при каждом обращении к корзине вы третируете базу запросами, так как добавление/изменение/удаление в корзине требует перерасчета.

Ajax всего лишь метод обмена с сервером, а все работать будет точно также.
laimas, Вы можете подсказать как это реализовать? я не понимаю...
мне же для начала нужно запретить стандартное поведение ссылки, далее создать переменные goods_id, price и qty (у меня количество товара всегда равно 1). Т.е. код будет выглядить так:

в HTML в строке: "<a href="?view=addtocart&amp;goods_id=<?=$product['goods_id']?>"><img class="addtocart" src="<?=TEMPLATE?>images/addcart.png" alt="Добавить в корзину" /></a>"

я добавляю ссылке класс class="addtocart", id="<?=$product['price']?>" и атрибут rel="<?=$product['goods_id']?>"

далее в файле с скриптами пишу такую функцию:
$(".addtocart").click(functions(e){

e.preventDefault(); // этим отменяю стандартное поведение ссылки
var good_id = $(this).attr("rel"); // здесь получаю id товара
var price = $(this).attr("id");// здесь получаю цену товара
var qty = 1;

// и вот после того как я получил значения в переменные, я не понимаю что делать....

$.ajax({

url: './', // обрабатываю я же всё здесь же в индексном файле
type: 'POST',
data: {good_id: good_id, price: price, qty: qty},
success:function{

},

error:function(){

}

});

Вот что мне писать в блока success и error? Помогите пожалуйста я не понимаю.
Ответить с цитированием
  #4 (permalink)  
Старый 14.10.2017, 21:02
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Сообщение от MikhailM1993
далее создать переменные goods_id, price и qty (у меня количество товара всегда равно 1).
Зачем? И если всегда по 1, то зачем же

// если в массиве cart уже есть добавляемый товар
$_SESSION['cart'][$goods_id]['qty'] += $qty;


может быть пусть и выбирает сколько ему надо, а не щелкать по одному много раз, ну это же неудобно.

И форматируйте свой код, ну невозможно его читать. Отформатируете, тогда можно и говорить, просмотрев что у вас есть.
Ответить с цитированием
  #5 (permalink)  
Старый 16.10.2017, 16:30
Новичок на форуме
Отправить личное сообщение для MikhailM1993 Посмотреть профиль Найти все сообщения от MikhailM1993
 
Регистрация: 14.10.2017
Сообщений: 5

laimas, по поводу количества, можно конечно сделать инпут где и вводить количество, но мой шаблон этого не подразумевает...

На данный момент у меня так:

Вот такая у меня корзина:

<div class="basket">
    <?php if($_SESSION['total_quantity']): ?>
        <a href="?view=cart"><img src="<?=TEMPLATE?>images/cart.png" alt="Корзина" /></a>
        <h4>Товаров в <a href="?view=cart">Вашей корзине:</a><br /> 
        <span><?=$_SESSION['total_quantity']?></span> на сумму <span><?=$_SESSION['total_sum']?></span> руб.</h4>
    <?php else: ?>
        <a href="?view=cart"><img src="<?=TEMPLATE?>images/cart.png" alt="Корзина" /></a>
        <h4>Товаров в <a href="?view=cart">Вашей корзине:</a>&nbsp;<span>0</span></h4>
    <?php endif; ?>
</div>


Вот так выводятся товары на странице:

<div class="goods">
    <a href="?view=product&amp;goods_id=<?=$product['goods_id']?>"><img width="200" height="200" src="<?=PRODUCTIMG?><?=$product['img']?>" alt="Картинка товара" /></a>
    <a class="good_name" href="?view=product&amp;goods_id=<?=$product['goods_id']?>"><?=$product['name']?></a>
    <p class="price">Цена: <span><?=$product['price']?> р.</span></p>
    <a rel="<?=$product['goods_id']?>" id="<?=$product['price']?>" href="?view=addtocart&amp;goods_id=<?=$product['goods_id']?>"><img class="addtocart" src="<?=TEMPLATE?>images/addcart.png" alt="Добавить в корзину" /></a>
</div>


Далее при клике на ссылку добавить в корзину вызываются функции:

addtocart:
function addtocart($goods_id, $qty = 1){
    if(isset($_SESSION['cart'][$goods_id])){
        // если в массиве cart уже есть добавляемый товар
        $_SESSION['cart'][$goods_id]['qty'] += $qty;
        return $_SESSION['cart'];
    }else{
        // если товар кладется в корзину впервые
        $_SESSION['cart'][$goods_id]['qty'] = $qty;
        return $_SESSION['cart'];
    }
}


total_sum:
function total_sum($goods){
    $total_sum = 0;

    $query = "SELECT goods_id, name, price, img
                FROM goods
                    WHERE goods_id IN (" .implode(',',array_keys($goods)). ")";

    $res = mysql_query($query) or die(mysql_error());
    while($row = mysql_fetch_assoc($res)){
        $_SESSION['cart'][$row['goods_id']]['name'] = $row['name'];
        $_SESSION['cart'][$row['goods_id']]['price'] = $row['price'];
        $_SESSION['cart'][$row['goods_id']]['img'] = $row['img'];
        $total_sum += $_SESSION['cart'][$row['goods_id']]['qty'] * $row['price'];
    }
    return $total_sum;
}


total_quantity:
function total_quantity(){
    $_SESSION['total_quantity'] = 0;
    foreach($_SESSION['cart'] as $key => $value){
        if(isset($value['price'])){
            // если получена цена товара из БД - суммируем кол-во
            $_SESSION['total_quantity'] += $value['qty'];
        }else{
            // иначе - удаляем такой ID из сессиии (корзины)
            unset($_SESSION['cart'][$key]);
        }
    }
}



Ну и далее как я и писал я не понимаю что делать что бы заставить данные передаваться AJAX-ом, вот мой набросок скрипта... возможно в корне не правильный но всё же...

$(".addtocart").click(functions(e){
    e.preventDefault(); // этим отменяю стандартное поведение ссылки
    // далее как я понимаю, мне нужно создать переменные и положить в них данные товара, например вот так.
    var good_id = $(this).attr("rel"); // здесь получаю id товара
    var price = $(this).attr("id");// здесь получаю цену товара
    var qty = 1;
    // и вот после того как я получил значения в переменные, я не понимаю что делать....
    $.ajax({
        url: './', // обрабатываю я же всё здесь же в индексном файле
        type: 'POST',
        data: {good_id: good_id, price: price, qty: qty},
        success:function{

        },
        error:function(){

        }
    };
});



P.S. Прошу прощения за долгий ответ, не было возможности ответить раньше.
Ответить с цитированием
  #6 (permalink)  
Старый 17.10.2017, 10:26
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Сначала по самой корзине. Вот что у вас происходит - total_sum($goods), и это постоянно ибо требуется всегда. А выгоднее не дергать БД постоянно, помещая в корзину минимум нужной информации о товаре. Для этого достаточно иметь структуру товаров в корзине как показано и получение всего товаров в корзине, и их сумма, это просто описать готовыми функциями:

$cart = [
    345 => [
        'count' => 4,
        'price'  => 150,
        'props' => ['name' => 'Печеньки', 'brand' => 'ООО Тесто']
    ],
    224 => [
        'count' => 3,
        'price'  => 250,
        'props' => ['name' => 'Семечки', 'brand' => 'АО Щелкай!']
    ]
];

//количество товаров в корзине
$count = array_sum(array_map('current', $cart));
//или с версии 5.5.0 можно так
$count = array_sum(array_column($cart, 'count'));

//сумма набранного
$total = array_sum(array_map('array_product', $cart));


Писать для этого такие функции как total_sum() и total_quantity() стоит ли?

Названия товаров и прочие параметры хранятся в массиве, значение которого функция array_product, при расчете суммы, возвращает равное 1, а значит не влияет на расчет.

При добавлении товаров в корзину из базы получается цена, название товара, и прочее необходимое. Корзина имеет два представления, но обслуживается одними и теми же данными, а значит для полного представления ее выгоднее иметь информацию уже в ней. То есть обращения к БД сводятся только к одноразовым запросам при добавлении нового товара в корзину.

Если товар добавляется только по одному, непонятен вообще второй аргумент функции addtocart(). И это связано с клиентской реализацией - как HTML структурой, так и функционалом. Обычно в таком случае, это кнопка "Добавить в корзину", серверу отправляется ID выбранного товара, он либо добавляется, либо икремент ранее добавленного. На клиенте при этом у товара будет информация типа "В корзине N штук".

Каким образом у вас клиентская часть организована (покажите результирующий html-код, а не шаблон на сервере с РНР вставками)?

Последний раз редактировалось laimas, 17.10.2017 в 10:35.
Ответить с цитированием
  #7 (permalink)  
Старый 18.10.2017, 10:55
Новичок на форуме
Отправить личное сообщение для MikhailM1993 Посмотреть профиль Найти все сообщения от MikhailM1993
 
Регистрация: 14.10.2017
Сообщений: 5

laimas,
Вот так выводиться товар:

<div class="goods">
    <a href="?view=product&amp;goods_id=48"><img src="baseimg/48.jpg" alt="Картинка товара" width="200" height="200"></a>
    <a class="good_name" href="?view=product&amp;goods_id=48">Товар №1</a>
    <p class="price">Цена: <span>4890 р.</span></p>
    <a href="?view=addtocart&amp;goods_id=48"><img class="addtocart" src="images/addcart.png" alt="Добавить в корзину"></a>
</div>


Если забыть про мои функции, которые я писал выше...

Мне же просто надо выбрать из БД цену товара (по его ID который можно взять из html кода) и занести данные товара (а именно ID товара, его цену и количество = 1) в массив $_SESSION['cart']. И вывести клиенту "В вашей корзине Х товаров на сумму N рублей". При повторном нажатии "Добавить в корзину" проверить если такой ID есть в корзине просто увеличить его количество на единицу.

У меня "затык" получается в том что я не понимаю как AJAXом отправить данные на сервер и получить от него ответ....
Ответить с цитированием
  #8 (permalink)  
Старый 18.10.2017, 22:00
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Упрощенно (на более полное нет времени). Сохранить под любым именем и запустить.

<?php
session_start();
//типа имитации БД
$base = [
  11 => ['name' => 'Товар №1', 'price' => 100],
  21 => ['name' => 'Товар №2', 'price' => 200],
  31 => ['name' => 'Товар №3', 'price' => 300]
];

//корзина
$cart = &$_SESSION['basket'];

//это очень упрощенно, а в реальности должо быть серьезнее
if($_POST['add']) {
    //есть ли товар в корзине?
    if(!array_key_exists($_POST['add'], $cart)) {
        //типа запроса к БД
        //в реальности же сложнее
        //1) использовать нужно либо mysqli, либо PDO, оригинальное расширение MySQL лучше забыть сразу
        //2) выше указанные расширения могут фильтровать данные извне, в случае оригинального расширения этому нужно уделять особенное внимание  
        $cart[$_POST['add']] = ['count' => 1, 'price' => $base[$_POST['add']]['price' ], 'prop' => ['name' => $base[$_POST['add']]['name' ]]]; 
    } else $cart[$_POST['add']]['count']++; //товар есть в корзине, добавляем еще один
    
    //ответ в формате JSON
    header('Content-Type: application/json');
    exit(json_encode([
                        'cart' => //состояние корзины
                            [
                                'count' => array_sum(array_map('current', $cart)), //товаров в корзине 
                                'total' => array_sum(array_map('array_product', $cart))], //на сумму 
                        'current' => $cart[$_POST['add']]['count'] //количество добавляемого товара в корзине
                     ])
    );
}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>Корзина</title>
<style>
li {
    list-style: none;
}
</style>
</head>
<body>
<ul>
    <li>Корзина</li>
    <li>Товаров: <span id="count">0</span> шт.</li>
    <li>На сумму: <span id="total">0</span> руб.</li>
</ul>
<div class="goods">
    <a href="?view=product&goods_id=11"><img src="baseimg/11.jpg" alt="Картинка товара" width="200" height="200"></a>
    <a class="good_name" href="?view=product&goods_id=11">Товар №1</a>
    <p class="price">Цена: <span>1000 р.</span></p>
    <button data-add="11">Добавить в корзину</button> <span></span>
</div>

<div class="goods">
    <a href="?view=product&goods_id=21"><img src="baseimg/21.jpg" alt="Картинка товара" width="200" height="200"></a>
    <a class="good_name" href="?view=product&goods_id=21">Товар №2</a>
    <p class="price">Цена: <span>200 р.</span></p>
    <button data-add="21">Добавить в корзину</button> <span></span>
</div>

<div class="goods">
    <a href="?view=product&goods_id=31"><img src="baseimg/31.jpg" alt="Картинка товара" width="200" height="200"></a>
    <a class="good_name" href="?view=product&goods_id=31">Товар №3</a>
    <p class="price">Цена: <span>300 р.</span></p>
    <button data-add="31">Добавить в корзину</button> <span></span>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
    $('button').click(function() {
        var btn = $('button').prop('disabled', true), //сделать кнопки добавления товара на время запроса недоступными
            bt = $(this); //текущая кнопка        
        $.post(location, {add: bt.data('add')}, function(data) {
            btn.prop('disabled', false); //разрешить добавление товаров
            //получен ответ
            if(data.cart) {
                $.each(data.cart, function(k, v) {
                    $('#'+k).text(v) //вывести информацию о корзине 
                });
                bt.next().text('В корзине: ' + data.current) //количество текущего товара в корзине        
            }
        }) 
    });
</script>
</body>
</html>

Последний раз редактировалось laimas, 18.10.2017 в 22:07.
Ответить с цитированием
  #9 (permalink)  
Старый 19.10.2017, 09:51
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,831

Стоит добавить проверку на корректность переданного id продукта и на наличие этого продукта в условной бд.
//После строки 14
if(!is_numeric($_POST['add']) or !isset($base[$_POST['add']]))
    exit(json_encode(['error'=>'Bad request']));
Ответить с цитированием
  #10 (permalink)  
Старый 19.10.2017, 10:27
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Nexus,
Зачем? В реалии это будет запрос к базе, а в таком случае проще поступить так:

if($id = (int)$_POST['add']) {
     //запрос БД, и если вернет, товар есть, иначе лажа
} //иначе лажа
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вопрос по ajax + mvc (нужна помощь) espltd Элементы интерфейса 0 25.08.2015 12:49
Помощь в реализации корзины на сайте polearmik Events/DOM/Window 1 09.02.2015 20:23
Объект ajax и приостановка функции kilohertz_. AJAX и COMET 5 18.01.2015 16:33
Увеличение числа параллельных ajax соединений 1lider AJAX и COMET 0 03.07.2014 17:46
Ajax таблица gofkane Работа 0 25.09.2011 11:53